package com.party.admin.biz.order;

import com.google.common.collect.Lists;
import com.google.common.collect.Maps;
import com.party.admin.biz.payquery.OrderQueryBizService;
import com.party.admin.web.dto.input.common.CommonInput;
import com.party.admin.web.dto.output.order.OrderFormOutput;
import com.party.common.paging.Page;
import com.party.common.utils.BigDecimalUtils;
import com.party.common.utils.LangUtils;
import com.party.common.utils.UUIDUtils;
import com.party.core.model.BaseModel;
import com.party.core.model.YesNoStatus;
import com.party.core.model.activity.Activity;
import com.party.core.model.member.MemberGroup;
import com.party.core.model.member.MerchantUtil;
import com.party.core.model.member.PackageCount;
import com.party.core.model.order.OrderForm;
import com.party.core.model.order.OrderStatus;
import com.party.core.model.order.OrderType;
import com.party.core.model.system.SysConfig;
import com.party.core.model.system.TargetType;
import com.party.core.model.wallet.Withdrawals;
import com.party.core.service.activity.IActivityService;
import com.party.core.service.activity.OrderActivityBizService;
import com.party.core.service.crowdfund.IProjectService;
import com.party.core.service.crowdfund.ISupportService;
import com.party.core.service.crowdfund.ITargetProjectService;
import com.party.core.service.goods.IGoodsCouponsService;
import com.party.core.service.goods.IGoodsService;
import com.party.core.service.member.IMemberActService;
import com.party.core.service.member.IMemberGroupService;
import com.party.core.service.member.IPackageCountService;
import com.party.core.service.order.IOrderFormService;
import com.party.core.service.order.IOrderRefundTradeService;
import com.party.core.service.order.biz.OrderFormBizService;
import com.party.core.service.system.ISysConfigService;
import com.party.core.service.wallet.biz.WithdrawalsBizService;
import com.party.pay.model.query.TradeStatus;
import org.apache.commons.lang3.StringUtils;
import org.apache.poi.ss.usermodel.Cell;
import org.apache.poi.ss.usermodel.Row;
import org.apache.poi.ss.usermodel.Sheet;
import org.apache.poi.xssf.streaming.SXSSFWorkbook;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

import java.sql.Connection;
import java.sql.DriverManager;
import java.sql.SQLException;
import java.sql.Statement;
import java.util.*;

@SuppressWarnings("all")
@Service
public class OrderBizService {
    @Autowired
    IOrderFormService orderFormService;
    @Autowired
    IGoodsCouponsService goodsCouponsService;
    @Autowired
    IMemberActService memberActService;
    @Autowired
    IActivityService activityService;
    @Autowired
    IProjectService projectService;
    @Autowired
    ISupportService supportService;
    @Autowired
    ITargetProjectService targetProjectService;
    @Autowired
    IOrderRefundTradeService orderRefundTradeService;
    @Autowired
    IGoodsService goodsService;
    @Autowired
    private WithdrawalsBizService withdrawalsBizService;
    @Autowired
    private IPackageCountService packageCountService;
    @Autowired
    private ISysConfigService sysConfigService;
    @Autowired
    private OrderFormBizService orderFormBizService;
    @Autowired
    private OrderQueryBizService orderQueryBizService;
    @Autowired
    private IMemberGroupService memberGroupService;

    @Value("${jdbc.url}")
    private String url;

    @Value("${jdbc.driver}")
    private String driver;

    @Value("${jdbc.username}")
    private String username;

    @Value("${jdbc.password}")
    private String password;

    Logger logger = LoggerFactory.getLogger(getClass());

    /**
     * 复制和删除已取消订单
     */
    public boolean copyAndDeleteCanceledOrder() {
        boolean successFlag = true;
        Connection connection = null;
        Statement statement = null;
        try {
            List<String> orderIds = orderFormService.getCanceledList();
            Class.forName(driver);
            connection = DriverManager.getConnection(url, username, password);
            statement = connection.createStatement();
            connection.setAutoCommit(false);//关闭自动提交事务，手动控制事务
            boolean lastOrder = false;
            int batchCount = 1000;
            String insertSql;
            String deleteSql;
            for (int i = 0; i < orderIds.size(); i++) {
                try {
                    String orderId = orderIds.get(i);
                    insertSql = String.format("INSERT INTO order_form_history SELECT * FROM order_form WHERE id = '%s'", orderId);
                    deleteSql = String.format("DELETE FROM order_form WHERE id = '%s'", orderId);
                    statement.addBatch(insertSql);
                    statement.addBatch(deleteSql);
                    if ((i + 1) % batchCount == 0) {
                        statement.executeBatch();
                        connection.commit();
                        statement.clearBatch();
                        logger.info("每" + batchCount + "个订单提交一次");
                    } else if (orderIds.size() - i < batchCount) {
                        lastOrder = true;
                    }
                    if (lastOrder && i == orderIds.size() - 1) {
                        statement.executeBatch();
                        connection.commit();
                        statement.clearBatch();
                        logger.info("不足" + batchCount + "个订单提交");
                    }
                } catch (SQLException e) {
                    successFlag = false;
                    connection.rollback();
                    logger.error("复制和删除订单异常回滚", e);
                    continue;
                }
            }
        } catch (Exception e) {
            try {
                successFlag = false;
                connection.rollback();
                logger.error("复制和删除订单异常回滚", e);
            } catch (SQLException e1) {
                e1.printStackTrace();
            }
        } finally {
            try {
                if (statement != null) {
                    statement.close();
                }
            } catch (SQLException e) {
                e.printStackTrace();
            }
            try {
                if (connection != null) {
                    statement.close();
                }
            } catch (SQLException e) {
                e.printStackTrace();
            }
        }
        return successFlag;
    }

    /**
     * 更新超时带支付订单为取消，同时取消相关业务
     */
    public Integer updateOvertimeOrderCancel() {
        int count = 0;
        List<String> orderIds = orderFormService.getNotPayList();
        for (String orderId : orderIds) {
            try {
                OrderForm orderForm = orderFormService.get(orderId);
                orderQueryBizService.doUpdateBusiness(orderForm, null);
                orderFormBizService.orderOvertimeCancel(orderId);
                count++;
            } catch (Exception e) {
                logger.error("更新超时带支付订单为取消异常：订单id——" + orderId, e);
                continue;
            }
        }
        return count;
    }

    /**
     * 恢复历史订单到订单表中
     *
     * @param orderId
     * @return
     */
    public boolean recoveryHistoryOrder(String orderId) {
        boolean successFlag = true;
        Connection connection = null;
        Statement statement = null;
        try {
            Class.forName(driver);
            connection = DriverManager.getConnection(url, username, password);
            statement = connection.createStatement();
            connection.setAutoCommit(false);//关闭自动提交事务，手动控制事务
            String insertSql = String.format("INSERT INTO order_form SELECT * FROM order_form_history WHERE id = '%s'", orderId);
            String deleteSql = String.format("DELETE FROM order_form_history WHERE id = '%s'", orderId);
            statement.addBatch(insertSql);
            statement.addBatch(deleteSql);
            statement.executeBatch();
            connection.commit();
            statement.clearBatch();
        } catch (Exception e) {
            try {
                successFlag = false;
                connection.rollback();
                logger.error("恢复历史订单到订单表中异常回滚", e);
            } catch (SQLException e1) {
                e1.printStackTrace();
            }
        } finally {
            try {
                if (statement != null) {
                    statement.close();
                }
            } catch (SQLException e) {
                e.printStackTrace();
            }
            try {
                if (connection != null) {
                    statement.close();
                }
            } catch (SQLException e) {
                e.printStackTrace();
            }
        }
        return successFlag;
    }

    /**
     * 作废订单
     *
     * @param orderForm 订单信息
     */
    @Transactional
    public void invalid(OrderForm orderForm) {
        orderForm.setStatus(OrderStatus.ORDER_STATUS_OTHER.getCode());
        orderFormService.update(orderForm);

        // 如果是活动订单
        if (OrderType.ORDER_ACTIVITY.getCode().equals(orderForm.getType())
                || OrderType.ORDER_COURSE.getCode().equals(orderForm.getType())) {

            // 取消报名
            memberActService.cancel(orderForm);
        } else if (OrderType.ORDER_NOMAL.getCode().equals(orderForm.getType())
                || OrderType.ORDER_CUSTOMIZED.getCode().equals(orderForm.getType())) {

            // 释放库存
            goodsService.releaseInventory(orderForm);
        }
    }

    /**
     * 订单总额
     *
     * @param orderForm 订单信息
     * @param params    参数集合
     * @param isTxz     是否是同行者订单
     * @param isSuccess 是否成功
     * @return 总金额
     */
    public Double getOrderTotal(OrderForm orderForm, Map<String, Object> params, boolean isTxz, boolean isSuccess) {
        Map<String, Object> newParams = Maps.newHashMap();
        if (isTxz) {
            Set<String> merchants = MerchantUtil.getTxzMerchants();
            newParams.put("txzMerchantId", merchants);
        }
        newParams.putAll(params);
        newParams.remove("isCrowdfund");
        newParams.put("isSuccess", isSuccess);
        Double totalPayment = orderFormService.getTotalPayment(orderForm, newParams);
        if (null != totalPayment) {
            return BigDecimalUtils.round(totalPayment, 2);
        }
        return 0d;
    }

    /**
     * 查询参数拼接
     *
     * @param orderForm   订单信息
     * @param tradeStatus 交易状态
     * @param params      查询集合
     * @return 拼装后参数
     */
    public Set<String> searchParams(OrderForm orderForm, String tradeStatus, Map<String, Object> params) {
        Set<String> tradeStatusSet = new HashSet<String>();
        if (StringUtils.isNotEmpty(tradeStatus)) {
            switch (Integer.valueOf(tradeStatus)) {
                case 1:
                    tradeStatusSet.add(TradeStatus.WX_SUCCESS.getCode());
                    tradeStatusSet.add(TradeStatus.ALI_TRADE_SUCCESS.getCode());
                    tradeStatusSet.add(TradeStatus.ALI_TRADE_FINISHED.getCode());
                    break;
                case 2:
                    tradeStatusSet.add(TradeStatus.WX_NOTPAY.getCode());
                    tradeStatusSet.add(TradeStatus.ALI_WAIT_BUYER_PAY.getCode());
                    break;
                case 3:
                    tradeStatusSet.add(TradeStatus.WX_REFUND.getCode());
                    tradeStatusSet.add(TradeStatus.ALI_TRADE_CLOSED.getCode());
                    orderForm.setStatus(OrderStatus.ORDER_STATUS_REFUND.getCode());
                    break;
                case 4:
                    tradeStatusSet.add(TradeStatus.WX_ORDERNOTEXIST.getCode());
                    tradeStatusSet.add(TradeStatus.ALI_TRADE_NOT_EXIST.getCode());
                    break;
                default:
                    break;
            }
        }
        if (tradeStatusSet.size() > 0) {
            params.put("tradeStatus", tradeStatusSet);
        }

        if (orderForm.getStatus() == null && StringUtils.isEmpty(tradeStatus)) {
//            Set<Integer> status = new HashSet<Integer>();
//            status.add(OrderStatus.ORDER_STATUS_TO_BE_PAID.getCode());
//            status.add(OrderStatus.ORDER_STATUS_HAVE_PAID.getCode());
//            status.add(OrderStatus.ORDER_STATUS_REFUND.getCode());
//            status.add(OrderStatus.ORDER_STATUS_OTHER.getCode());
//            params.put("status", status);
        }
        return tradeStatusSet;
    }

    /**
     * 活动，众筹已支付的订单总额
     *
     * @param isTxz    是否是同行者订单
     * @param memberId 会员编号
     * @param type     类型
     * @return 订单总额
     */
    public Double getOrderTotal(boolean isTxz, String memberId, Integer type, Map<String, Object> params) {
        OrderForm orderForm = new OrderForm();
        orderForm.setInitiatorId(memberId);

        // 已支付
        orderForm.setStatus(OrderStatus.ORDER_STATUS_HAVE_PAID.getCode());
        orderForm.setDelFlag(BaseModel.DEL_FLAG_NORMAL);
        orderForm.setType(type);
        if (params == null) {
            params = new HashMap<String, Object>();
        }
        Set<Integer> orderTypes = new HashSet<Integer>();

        if (isTxz) {
            Set<String> merchants = MerchantUtil.getTxzMerchants();
            params.put("txzMerchantId", merchants);
        }

        params.put("types", orderTypes);
        params.put("isCrowdfund", 0);
        params.put("payment", 0);
        return orderFormService.getTotalPayment(orderForm, params);
    }

    /**
     * 获取余额
     *
     * @param memberId 会员编号
     * @param type     订单类型
     * @param withType 提现类型
     * @return
     */
    public double getTotalAccount(String memberId, Integer type, Integer withType) {
        Double orderTotal = getOrderTotal(true, memberId, type, null);
        Double withdrawalTotal = withdrawalsBizService.getWithdrawalTotal(memberId, withType,null);

        double blance = 0.0;

        if (orderTotal == null) {
            orderTotal = 0.0;
            blance = 0;
        }
        if (withdrawalTotal == null) {
            withdrawalTotal = 0.0;
            blance = orderTotal;
        }

        if (orderTotal != null && withdrawalTotal != null) {
            blance = BigDecimalUtils.sub(orderTotal, withdrawalTotal);
        }
        return blance;
    }

    public Map<String, Object> memberInfoBiz(String memberId) {
        Map<String, Object> resultParams = Maps.newHashMap();
        // 余额
        double totalPayment = getTotalAccount(memberId, null, Withdrawals.TYPE_BALANCE);
        resultParams.put("totalPayment", totalPayment);

        PackageCount packageCount = packageCountService.getUnique(new PackageCount(memberId, TargetType.PUSH_SMS.getCode()));
        if (packageCount == null) {
            packageCount = new PackageCount();
            // 短信预警默认配置
            SysConfig smsWarnConfig = sysConfigService.findByCode(PackageCount.SMS_WARN_NUM_DEFAULT);
            // 短信超出使用默认配置
            SysConfig smsExcessConfig = sysConfigService.findByCode(PackageCount.SMS_EXCESS_NUM_DEFAULT);
            packageCount.setIsOpen(YesNoStatus.NO_NEW.getCode()); // 默认关闭
            packageCount.setIsAllowExcess(YesNoStatus.YES.getCode()); // 默认开启
            packageCount.setIsWarned(YesNoStatus.NO_NEW.getCode()); // 默认关闭
            if (smsWarnConfig != null) {
                packageCount.setWarnNum(Integer.valueOf(smsWarnConfig.getValue()));
            } else {
                packageCount.setWarnNum(0);
            }
            if (smsExcessConfig != null) {
                packageCount.setExcessNum(Integer.valueOf(smsExcessConfig.getValue()));
            } else {
                packageCount.setExcessNum(0);
            }
        }
        resultParams.put("packageCount", packageCount);

        MemberGroup member = memberGroupService.get(memberId);
        resultParams.put("member", member);
        return resultParams;
    }

    /**
     * 获取主题的订单数据
     *
     * @param eventId 主题编号
     * @return
     */
    public Map<String, Double> getOrderData(String eventId,Integer payType) {
        // 支付总额
        Double payMoney = orderFormService.getOrderData(eventId, OrderStatus.ORDER_STATUS_HAVE_PAID.getCode(),payType);
        // 退款总额
        Double refundMoney = orderFormService.getOrderData(eventId, OrderStatus.ORDER_STATUS_REFUND.getCode(),payType);

        // 累计总额
        Double totalMoney = BigDecimalUtils.add(payMoney, refundMoney);
        totalMoney = BigDecimalUtils.round(totalMoney, 2);

        Map<String, Double> orderData = Maps.newHashMap();
        orderData.put("totalMoney", totalMoney);
        orderData.put("refundMoney", BigDecimalUtils.round(refundMoney, 2));
        orderData.put("remainMoney", BigDecimalUtils.round(payMoney, 2));
        return orderData;
    }

/*    *//**
     * 获取主题的订单数据
     *
     * @param eventId 主题编号
     * @return
     *//*
    public Map<String, Double> getDpOrderData(String eventId) {
        // 支付总额
        Double payMoney = orderFormService.getDpOrderData(eventId, OrderStatus.ORDER_STATUS_HAVE_PAID.getCode());
        // 退款总额
        Double refundMoney = orderFormService.getDpOrderData(eventId, OrderStatus.ORDER_STATUS_REFUND.getCode());

        // 累计总额
        Double totalMoney = BigDecimalUtils.add(payMoney, refundMoney);
        totalMoney = BigDecimalUtils.round(totalMoney, 2);

        // 剩余总额
        Double remainMoney = BigDecimalUtils.sub(totalMoney, refundMoney);
        remainMoney = BigDecimalUtils.round(remainMoney, 2);

        Map<String, Double> orderData = Maps.newHashMap();
        orderData.put("totalMoney", totalMoney);
        orderData.put("refundMoney", BigDecimalUtils.round(refundMoney, 2));
        orderData.put("remainMoney", remainMoney);
        return orderData;
    }*/


    /**
     * 初始化累计订单数和累计资金数
     *
     * @param activityId 活动id
     * @param type       类型 1：众筹活动 0：普通活动
     */
    public void initOrderNumAndTotalMoney(String activityId, Integer type) {
        Map<String, Object> activityData = Maps.newHashMap();
        if (YesNoStatus.YES.getCode().equals(type)) {
            // 是众筹活动
            activityData.putAll(orderFormService.statisticZcActivityData(activityId));
        } else if (YesNoStatus.NO.getCode().equals(type)) {
            // 是普通活动
            activityData.putAll(orderFormService.statisticActivityData(activityId));
        }
        Long orderNum = activityData.get("orderNum") != null ? (Long) activityData.get("orderNum") : 0L;
        Double totalMoney = activityData.get("totalMoney") != null ? (Double) activityData.get("totalMoney") : 0d;

        if (orderNum != 0L && totalMoney != 0d) {
            Activity activity = activityService.get(activityId);
            activity.setOrderNum(orderNum);
            activity.setTotalMoney(totalMoney);
            activity.setUpdateDate(null);
            activityService.update(activity);
        }
    }

    @Autowired
    private OrderActivityBizService orderActivityBizService;
    /**
     * 用户订单列表
     * @param page
     * @return
     */
    public List<OrderFormOutput> memberOrderList(Page page, OrderForm orderForm, Map<String, Object> params,String memberId, String memberName) {
        if (orderForm == null) {
            orderForm = new OrderForm();
        }
        orderForm.setInitiatorId(memberId);
        orderForm.setStatus(OrderStatus.ORDER_STATUS_HAVE_PAID.getCode()); // 已支付

        params.put("isCrowdfund", "0");
        params.put("payment", 0);

        List<OrderForm> orderForms = this.getNewOrderList(params, null, memberName, page, orderForm);
        List<OrderFormOutput> orderFormOutputs = LangUtils.transform(orderForms, input -> {
            OrderFormOutput orderFormOutput = OrderFormOutput.transform(input);
            String label = OrderType.getValue(input.getType());
            orderFormOutput.setTypeName(label);
            // 获取商户名称
            String merchantName = orderActivityBizService.
                    getMerchantName(input.getMerchantId(), input.getPaymentWay(), input.getInitiatorId(), input.getMerchantName());
            orderFormOutput.setMerchantName(merchantName);
            return orderFormOutput;
        });
        return orderFormOutputs;
    }

    /**
     * @param params        查询参数
     * @param initiatorName 所属者
     * @param memberName    下单者
     * @param page          分页
     * @param orderForm     订单
     * @return java.util.List<com.party.core.model.order.OrderForm>
     * @Author yifeng
     * @Description 订单管理查询
     * @Date 13:39 2018/12/29
     **/
    public List<OrderForm> getNewOrderList(Map<String, Object> params, String initiatorName,
                                           String memberName, Page page, OrderForm orderForm) {

        // 判断输入的是否为商户号
        params.put("merchantIdBoolean", StringUtils.isNumeric(orderForm.getMerchantId()));

        // 判断输入的是否为id
        boolean initiatorBoolean = UUIDUtils.isUUID(initiatorName);
        boolean memberBoolean = UUIDUtils.isUUID(memberName);
        params.put("initiatorBoolean", initiatorBoolean);
        params.put("memberBoolean", memberBoolean);

        long start = System.currentTimeMillis();
        Integer totalCount;
        if ((StringUtils.isNotEmpty(initiatorName) && !initiatorBoolean)
                || (StringUtils.isNotEmpty(memberName) && !memberBoolean)) {
            totalCount = orderFormService.newWebListCountNew(orderForm, params);
        } else {
            totalCount = orderFormService.newWebListCount(orderForm, params);
        }

        long end = System.currentTimeMillis();
        System.out.println("count sql执行完" + (end - start) / 1000);

        page.setTotalCount(totalCount);

        Map<String, Object> pageParams = CommonInput.appendPageParams(page);
        params.putAll(pageParams);

        start = System.currentTimeMillis();

        List<OrderForm> orderForms = Lists.newArrayList();
        if ((StringUtils.isNotEmpty(initiatorName) && !initiatorBoolean)
                || (StringUtils.isNotEmpty(memberName) && !memberBoolean)) {
            orderForms = orderFormService.newWebListPageNew(orderForm, params);
        } else {
            orderForms = orderFormService.newWebListPage(orderForm, params);
        }

        end = System.currentTimeMillis();
        System.out.println("page sql执行完" + (end - start) / 1000);
        return orderForms;
    }

    public SXSSFWorkbook exportTxzMerchantMember() {
        List<Map<String, Object>> txzOrderMembers = orderFormService.getTxzOrderMember(MerchantUtil.TXZ_WWZ_MERCHANT_SSFW_ID);

        SXSSFWorkbook wb = new SXSSFWorkbook();
        Sheet sheet0 = wb.createSheet("使用赛事服务商户的机构");

        String[] titles = {
                "名称", "金额"
        };

        // 标题
        Row titleRow = sheet0.createRow(0);
        for (int i = 0; i < titles.length; i++) {
            Cell cell = titleRow.createCell(i);
            cell.setCellValue(titles[i]);
        }

        List<Object> values = Lists.newArrayList();

        for (int j = 0; j < txzOrderMembers.size(); j++) {
            Map<String, Object> objectMap = txzOrderMembers.get(j);
            if (null == objectMap) {
                continue;
            }

            // 名称
            Object orgName = objectMap.get("orgName");
            // 金额
            Object totalPayment = objectMap.get("totalPayment");

            values.clear();
            values.add(orgName);
            values.add(totalPayment);

            Row dataRow = sheet0.createRow(j + 1);

            for (int k = 0; k < values.size(); k++) {
                Cell dataCell = dataRow.createCell(k);

                if (null != values.get(k)) {
                    if (values.get(k) instanceof Double) {
                        dataCell.setCellValue(Double.valueOf(values.get(k).toString()));
                    } else {
                        dataCell.setCellValue(values.get(k).toString());
                    }
                } else {
                    dataCell.setCellValue("");
                }
            }
        }
        return wb;
    }
}
